Vectors
A vector is a growable, heap-allocated array that stores values of the same type in contiguous memory.
Think of Vec<T> as: “An array that can grow and shrink safely.”
let v = vec![1, 2, 3];
- Stores elements of type i32
- Allocated on the heap
- Size can change at runtime
Explicit Type
let v: Vec<i32> = Vec::new();
Vec<T> is generic — it works with any type.
Key Characteristics of Vec<T>
| Feature | Vector |
|---|---|
| Size | Dynamic |
| Memory | Heap |
| Grow/Shrink | ✅ Yes |
| Indexing | O(1) |
| Ownership | Owns elements |
| Safety | Bounds-checked |
Creating Vectors
- Empty Vector:
let mut v: Vec<i32> = Vec::new(); - Using vec! Macro:
let v = vec![10, 20, 30]; - Initialize with Repeated Values:
let v = vec![0; 5];Creates:[0, 0, 0, 0, 0]
Adding Elements
Using push()
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
Vector grows automatically.
Capacity vs Length
let mut v = Vec::with_capacity(5);
v.push(1);
v.push(2);
println!("Length: {}", v.len());
println!("Capacity: {}", v.capacity());
len()→ number of elementscapacity()→ allocated space
Accessing Elements
Using Index (Risky)
let v = vec![10, 20, 30];
println!("{}", v[1]); // 20
Panic if index is out of bounds.
Safe Access Using .get()
let v = vec![10, 20, 30];
match v.get(5) {
Some(value) => println!("{}", value),
None => println!("Index out of bounds"),
}
Iterating Over Vectors
Immutable Iteration
let v = vec![1, 2, 3];
for x in &v {
println!("{}", x);
}
Mutable Iteration
let mut v = vec![1, 2, 3];
for x in &mut v {
*x *= 2;
}
Vector becomes: [2, 4, 6]
Consuming Iteration
let v = vec![1, 2, 3];
for x in v {
println!("{}", x);
}
v is moved and can’t be used after.
Removing Elements
Remove Last Element
let mut v = vec![1, 2, 3];
let last = v.pop();
last is Option<i32>
Remove by Index
let mut v = vec![10, 20, 30];
v.remove(1);
Vector becomes: [10, 30]
Slicing Vectors (&[T])
Create a Slice
let v = vec![1, 2, 3, 4, 5];
let slice = &v[1..4];
Type: &[i32]
Why Slices Matter
- No ownership transfer
- Works for arrays and vectors
- Ideal for function parameters
fn print_slice(slice: &[i32]) {
for x in slice {
println!("{}", x);
}
}
Vectors and Ownership
Moving a Vector
let v1 = vec![1, 2, 3];
let v2 = v1; // ownership moved
v1 is no longer valid.
Borrowing a Vector
let v = vec![1, 2, 3];
print_vec(&v);
fn print_vec(v: &Vec<i32>) {
println!("{:?}", v);
}
Better:
fn print_vec(v: &[i32]) {
println!("{:?}", v);
}
Storing Different Types (Using Enums)
Vectors can store only one type, but enums help.
enum Value {
Int(i32),
Float(f64),
Text(String),
}
let v = vec![
Value::Int(10),
Value::Float(3.14),
Value::Text(String::from("Rust")),
];
Common Vector Methods
| Method | Purpose |
|---|---|
push() | Add element |
pop() | Remove last |
len() | Number of elements |
capacity() | Allocated space |
clear() | Remove all |
contains() | Check value |
sort() | Sort elements |
Arrays vs Vectors (Quick Recap)
| Feature | Array | Vector |
|---|---|---|
| Size | Fixed | Dynamic |
| Memory | Stack | Heap |
| Resize | ❌ | ✅ |
| Use case | Known size | Runtime data |